import { Injectable, BadRequestException, ForbiddenException } from '@nestjs/common'
import { DatabaseService } from '../../database/database.service'
import { LoggerService } from '../../common/logger/logger.service'
import { UserRole } from '@prisma/client'
import * as fs from 'fs'
import * as path from 'path'
import * as os from 'os'

@Injectable()
export class SystemService {
  constructor(
    private readonly databaseService: DatabaseService,
    private readonly logger: LoggerService
  ) {}

  // 获取系统信息
  async getSystemInfo(userRole: UserRole) {
    try {
      if (userRole !== UserRole.ADMIN && userRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('无权限访问系统信息')
      }

      const [userStats, postStats, fileStats, commentStats] = await Promise.all([
        this.getUserStats(),
        this.getPostStats(),
        this.getFileStats(),
        this.getCommentStats()
      ])

      const systemInfo = {
        server: {
          platform: os.platform(),
          arch: os.arch(),
          nodeVersion: process.version,
          uptime: process.uptime(),
          memory: {
            total: os.totalmem(),
            free: os.freemem(),
            used: process.memoryUsage()
          },
          cpu: os.cpus(),
          loadAverage: os.loadavg()
        },
        database: {
          users: userStats,
          posts: postStats,
          files: fileStats,
          comments: commentStats
        },
        timestamp: new Date()
      }

      return systemInfo
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error
      }
      this.logger.error(`Failed to get system info: ${error.message}`, error.stack, 'SystemService')
      throw new BadRequestException('获取系统信息失败')
    }
  }

  // 获取系统统计数据
  async getSystemStats(userRole: UserRole) {
    try {
      if (userRole !== UserRole.ADMIN && userRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('无权限访问系统统计')
      }

      const [totalUsers, totalPosts, totalFiles, totalComments, recentActivity] = await Promise.all([
        this.databaseService.user.count(),
        this.databaseService.post.count(),
        this.databaseService.file.count(),
        this.databaseService.comment.count(),
        this.getRecentActivity()
      ])

      return {
        overview: {
          totalUsers,
          totalPosts,
          totalFiles,
          totalComments
        },
        recentActivity
      }
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error
      }
      this.logger.error(`Failed to get system stats: ${error.message}`, error.stack, 'SystemService')
      throw new BadRequestException('获取系统统计失败')
    }
  }

  // 获取系统日志
  async getSystemLogs(
    params: {
      page?: number
      limit?: number
      level?: string
      startDate?: string
      endDate?: string
    },
    userRole: UserRole
  ) {
    try {
      if (userRole !== UserRole.ADMIN && userRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('无权限访问系统日志')
      }

      const { page = 1, limit = 50 } = params

      // 这里应该从日志文件或日志数据库中读取日志
      // 由于我们使用的是Winston，可以从日志文件中读取
      const logsDir = path.join(process.cwd(), 'logs')
      const logs = await this.readLogFiles(logsDir, params)

      const startIndex = (page - 1) * limit
      const endIndex = startIndex + limit
      const paginatedLogs = logs.slice(startIndex, endIndex)

      return {
        data: paginatedLogs,
        pagination: {
          page,
          limit,
          total: logs.length,
          pages: Math.ceil(logs.length / limit)
        }
      }
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error
      }
      this.logger.error(`Failed to get system logs: ${error.message}`, error.stack, 'SystemService')
      throw new BadRequestException('获取系统日志失败')
    }
  }

  // 清理系统数据
  async cleanupSystem(
    options: {
      cleanLogs?: boolean
      cleanTempFiles?: boolean
      cleanOldSessions?: boolean
      daysToKeep?: number
    },
    userRole: UserRole
  ) {
    try {
      if (userRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('无权限执行系统清理')
      }

      const { cleanLogs = false, cleanTempFiles = false, cleanOldSessions = false, daysToKeep = 30 } = options
      const results: any = {}

      // 清理旧日志
      if (cleanLogs) {
        results.logs = await this.cleanupLogs(daysToKeep)
      }

      // 清理临时文件
      if (cleanTempFiles) {
        results.tempFiles = await this.cleanupTempFiles()
      }

      // 清理过期会话
      if (cleanOldSessions) {
        results.sessions = await this.cleanupOldSessions(daysToKeep)
      }

      this.logger.log('System cleanup completed', 'SystemService')
      return {
        message: '系统清理完成',
        results
      }
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error
      }
      this.logger.error(`Failed to cleanup system: ${error.message}`, error.stack, 'SystemService')
      throw new BadRequestException('系统清理失败')
    }
  }

  // 备份数据库
  async backupDatabase(userRole: UserRole) {
    try {
      if (userRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('无权限执行数据库备份')
      }

      // 这里应该实现实际的数据库备份逻辑
      // 由于使用的是Prisma，可以考虑使用pg_dump或其他数据库特定的备份工具
      const backupFileName = `backup_${new Date().toISOString().replace(/[:.]/g, '-')}.sql`
      const backupPath = path.join(process.cwd(), 'backups', backupFileName)

      // 确保备份目录存在
      const backupDir = path.dirname(backupPath)
      if (!fs.existsSync(backupDir)) {
        fs.mkdirSync(backupDir, { recursive: true })
      }

      // 这里应该执行实际的备份命令
      // 例如：pg_dump DATABASE_URL > backupPath

      this.logger.log(`Database backup created: ${backupFileName}`, 'SystemService')
      return {
        message: '数据库备份成功',
        fileName: backupFileName,
        path: backupPath,
        timestamp: new Date()
      }
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error
      }
      this.logger.error(`Failed to backup database: ${error.message}`, error.stack, 'SystemService')
      throw new BadRequestException('数据库备份失败')
    }
  }

  // 获取系统配置
  async getSystemConfig(userRole: UserRole) {
    try {
      if (userRole !== UserRole.ADMIN && userRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('无权限访问系统配置')
      }

      // 返回非敏感的系统配置信息
      const config = {
        app: {
          name: process.env.APP_NAME || 'Node.js CMS',
          version: process.env.APP_VERSION || '1.0.0',
          environment: process.env.NODE_ENV || 'development'
        },
        features: {
          fileUpload: true,
          emailNotifications: !!process.env.SMTP_HOST,
          caching: !!process.env.REDIS_URL
        },
        limits: {
          maxFileSize: process.env.MAX_FILE_SIZE || '10MB',
          maxUsers: process.env.MAX_USERS || 'unlimited',
          maxPosts: process.env.MAX_POSTS || 'unlimited'
        }
      }

      return config
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error
      }
      this.logger.error(`Failed to get system config: ${error.message}`, error.stack, 'SystemService')
      throw new BadRequestException('获取系统配置失败')
    }
  }

  // 更新系统配置
  async updateSystemConfig(config: any, userRole: UserRole) {
    try {
      if (userRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('无权限修改系统配置')
      }

      // 这里应该实现配置更新逻辑
      // 可以将配置保存到数据库或配置文件中

      this.logger.log('System config updated', 'SystemService')
      return {
        message: '系统配置更新成功',
        config,
        timestamp: new Date()
      }
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error
      }
      this.logger.error(`Failed to update system config: ${error.message}`, error.stack, 'SystemService')
      throw new BadRequestException('更新系统配置失败')
    }
  }

  // 私有方法：获取用户统计
  private async getUserStats() {
    const [total, active, byRole] = await Promise.all([
      this.databaseService.user.count(),
      this.databaseService.user.count({ where: { isActive: true } }),
      this.databaseService.user.groupBy({
        by: ['role'],
        _count: { id: true }
      })
    ])

    return {
      total,
      active,
      inactive: total - active,
      byRole: byRole.reduce(
        (acc, item) => {
          acc[item.role] = item._count.id
          return acc
        },
        {} as Record<string, number>
      )
    }
  }

  // 私有方法：获取文章统计
  private async getPostStats() {
    const [total, published, draft, byStatus] = await Promise.all([
      this.databaseService.post.count(),
      this.databaseService.post.count({ where: { status: 'PUBLISHED' } }),
      this.databaseService.post.count({ where: { status: 'DRAFT' } }),
      this.databaseService.post.groupBy({
        by: ['status'],
        _count: { id: true }
      })
    ])

    return {
      total,
      published,
      draft,
      byStatus: byStatus.reduce(
        (acc, item) => {
          acc[item.status] = item._count.id
          return acc
        },
        {} as Record<string, number>
      )
    }
  }

  // 私有方法：获取文件统计
  private async getFileStats() {
    const [total, totalSize, byType] = await Promise.all([
      this.databaseService.file.count(),
      this.databaseService.file.aggregate({ _sum: { size: true } }),
      this.databaseService.file.groupBy({
        by: ['mimeType'],
        _count: { id: true },
        _sum: { size: true }
      })
    ])

    return {
      total,
      totalSize: totalSize._sum.size || 0,
      byType: byType.map(item => ({
        mimeType: item.mimeType,
        count: item._count.id,
        size: item._sum.size || 0
      }))
    }
  }

  // 私有方法：获取评论统计
  private async getCommentStats() {
    const [total, approved, pending, byStatus] = await Promise.all([
      this.databaseService.comment.count(),
      this.databaseService.comment.count({ where: { status: 'APPROVED' } }),
      this.databaseService.comment.count({ where: { status: 'PENDING' } }),
      this.databaseService.comment.groupBy({
        by: ['status'],
        _count: { id: true }
      })
    ])

    return {
      total,
      approved,
      pending,
      byStatus: byStatus.reduce(
        (acc, item) => {
          acc[item.status] = item._count.id
          return acc
        },
        {} as Record<string, number>
      )
    }
  }

  // 私有方法：获取最近活动
  private async getRecentActivity() {
    const [recentPosts, recentUsers, recentComments] = await Promise.all([
      this.databaseService.post.findMany({
        orderBy: { createdAt: 'desc' },
        take: 5,
        select: {
          id: true,
          title: true,
          createdAt: true,
          author: { select: { username: true } }
        }
      }),
      this.databaseService.user.findMany({
        orderBy: { createdAt: 'desc' },
        take: 5,
        select: {
          id: true,
          username: true,
          createdAt: true
        }
      }),
      this.databaseService.comment.findMany({
        orderBy: { createdAt: 'desc' },
        take: 5,
        select: {
          id: true,
          content: true,
          createdAt: true,
          user: { select: { username: true } },
          post: { select: { title: true } }
        }
      })
    ])

    return {
      recentPosts,
      recentUsers,
      recentComments
    }
  }

  // 私有方法：读取日志文件
  private async readLogFiles(logsDir: string, params: any): Promise<any[]> {
    const logs: any[] = []

    if (!fs.existsSync(logsDir)) {
      return logs
    }

    const files = fs.readdirSync(logsDir)

    for (const file of files) {
      if (file.endsWith('.log')) {
        const filePath = path.join(logsDir, file)
        const content = fs.readFileSync(filePath, 'utf8')
        const lines = content.split('\n').filter(line => line.trim())

        for (const line of lines) {
          try {
            const logEntry = JSON.parse(line)
            logs.push(logEntry)
          } catch (error) {
            // 忽略无法解析的日志行
          }
        }
      }
    }

    // 按时间戳排序
    logs.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())

    return logs
  }

  // 私有方法：清理日志
  private async cleanupLogs(daysToKeep: number) {
    const logsDir = path.join(process.cwd(), 'logs')
    const cutoffDate = new Date()
    cutoffDate.setDate(cutoffDate.getDate() - daysToKeep)

    let deletedCount = 0

    if (fs.existsSync(logsDir)) {
      const files = fs.readdirSync(logsDir)

      for (const file of files) {
        const filePath = path.join(logsDir, file)
        const stats = fs.statSync(filePath)

        if (stats.mtime < cutoffDate) {
          fs.unlinkSync(filePath)
          deletedCount++
        }
      }
    }

    return { deletedCount, daysToKeep }
  }

  // 私有方法：清理临时文件
  private async cleanupTempFiles() {
    const tempDir = path.join(process.cwd(), 'temp')
    let deletedCount = 0

    if (fs.existsSync(tempDir)) {
      const files = fs.readdirSync(tempDir)

      for (const file of files) {
        const filePath = path.join(tempDir, file)
        fs.unlinkSync(filePath)
        deletedCount++
      }
    }

    return { deletedCount }
  }

  // 私有方法：清理过期会话
  private async cleanupOldSessions(daysToKeep: number) {
    const cutoffDate = new Date()
    cutoffDate.setDate(cutoffDate.getDate() - daysToKeep)

    const result = await this.databaseService.session.deleteMany({
      where: {
        updatedAt: {
          lt: cutoffDate
        }
      }
    })

    return { deletedCount: result.count, daysToKeep }
  }
}
